<i18n locale="zh-CN" lang="yaml">
Related Contents: 关联内容
Exporting with related contents: 导出并附带关联内容
Exported passwords will be changed to an empty string by force: 导出的密码将会强制变更为空字符串
Exported Connectors will not include sensitive data (such as password), please re-entered them after import: 导出的连接器不包含敏感数据（如密码等），请在导入后重新输入
Meaningful notes can provide a reliable reference for the future: 有意义的备注可以为将来提供可靠的参考
Please select at least one Script Set: 请选择导出脚本集
Please input note: 请输入备注
Data exported: 数据已导出
'Exported content has been downloaded as a zip file:': '导出内容已作为 zip 文件下载：'
</i18n>

<!-- Generated by OpenCC START -->
<i18n locale="zh-HK" lang="yaml">
Data exported: 數據已導出
Exported Connectors will not include sensitive data (such as password), please re-entered them after import: 導出的連接器不包含敏感數據（如密碼等），請在導入後重新輸入
'Exported content has been downloaded as a zip file:': 導出內容已作為 zip 文件下載：
Exported passwords will be changed to an empty string by force: 導出的密碼將會強制變更為空字符串
Exporting with related contents: 導出並附帶關聯內容
Meaningful notes can provide a reliable reference for the future: 有意義的備註可以為將來提供可靠的參考
Please input note: 請輸入備註
Please select at least one Script Set: 請選擇導出腳本集
Related Contents: 關聯內容
</i18n>
<i18n locale="zh-TW" lang="yaml">
Data exported: 資料已匯出
Exported Connectors will not include sensitive data (such as password), please re-entered them after import: 匯出的聯結器不包含敏感資料（如密碼等），請在匯入後重新輸入
'Exported content has been downloaded as a zip file:': 匯出內容已作為 zip 檔案下載：
Exported passwords will be changed to an empty string by force: 匯出的密碼將會強制變更為空字串
Exporting with related contents: 匯出並附帶關聯內容
Meaningful notes can provide a reliable reference for the future: 有意義的備註可以為將來提供可靠的參考
Please input note: 請輸入備註
Please select at least one Script Set: 請選擇匯出指令碼集
Related Contents: 關聯內容
</i18n>
<!-- Generated by OpenCC END -->

<template>
  <el-dialog
    id="ScriptSetSetup"
    :visible.sync="show"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    width="750px">

    <template slot="title">
      {{ $t('Script Set Export') }}
    </template>

    <el-container direction="vertical">
      <el-main>
        <div class="export-form">
          <el-form ref="form" label-width="135px" :model="form" :rules="formRules">
            <el-form-item :label="$t('Script Set')" prop="scriptSetIds">
              <el-select
                v-model="form.scriptSetIds"
                multiple
                filterable
                :filter-method="T.debounce(doScriptSetFilter)"
                :placeholder="$t('Please select')">
                <el-option
                  v-for="item in selectScriptSetOptions"
                  :key="item.id"
                  :label="item.title || item.id"
                  :value="item.id"
                  :disabled="item.isLocked">
                  <i class="fa fa-fw" :class="item.isLocked ? 'fa-lock' : 'fa-folder'"></i>
                  <span class="select-item-name">{{ item.title || item.id }}</span>
                  <code class="select-item-id code-font">{{ $t('(') }}ID: {{ item.id }}{{ $t(')') }}</code>
                </el-option>
              </el-select>
            </el-form-item>

            <el-form-item :label="$t('Related Contents')">
              <el-checkbox size="medium" border v-model="form.includeSyncAPIs"><i class="fa fa-fw fa-link"></i> {{ $t('Sync API') }}</el-checkbox>
              <el-checkbox size="medium" border v-model="form.includeAsyncAPIs"><i class="fa fa-fw fa-tasks"></i> {{ $t('Async API') }}</el-checkbox>
              <el-checkbox size="medium" border v-model="form.includeCronJobs"><i class="fa fa-fw fa-clock-o"></i> {{ $t('Cron Job') }}</el-checkbox>
              <InfoBlock :title="$t('Exporting with related contents')" />
            </el-form-item>

            <el-form-item :label="$t('Connector')" prop="connectorIds">
              <el-select
                v-model="form.connectorIds"
                multiple
                filterable
                :filter-method="T.debounce(doConnectorFilter)"
                :placeholder="$t('Please select')">
                <el-option
                  v-for="item in selectConnectorOptions"
                  :key="item.id"
                  :label="item.title || item.id"
                  :value="item.id">
                  <el-tag class="select-item-tag"
                    :type="C.CONNECTOR_MAP.get(item.type).tagType"
                    size="mini">{{ C.CONNECTOR_MAP.get(item.type).name }}</el-tag>
                  <span class="select-item-name">{{ item.title || item.id }}</span>
                  <code class="select-item-id code-font">{{ $t('(') }}ID: {{ item.id }}{{ $t(')') }}</code>
                </el-option>
              </el-select>
              <InfoBlock v-if="T.notNothing(form.connectorIds)" type="warning" :title="$t('Exported Connectors will not include sensitive data (such as password), please re-entered them after import')" />
            </el-form-item>

            <el-form-item :label="$t('ENV')" prop="envVariableIds">
              <el-select
                v-model="form.envVariableIds"
                multiple
                filterable
                :filter-method="T.debounce(doEnvVariableFilter)"
                :placeholder="$t('Please select')">
                <el-option
                  v-for="item in selectEnvVariableOptions"
                  :key="item.id"
                  :label="item.title || item.id"
                  :value="item.id">
                  <el-tag class="select-item-tag"
                    :type="C.ENV_VARIABLE_MAP.get(item.autoTypeCasting).tagType"
                    size="mini">{{ C.ENV_VARIABLE_MAP.get(item.autoTypeCasting).name }}</el-tag>
                  <span class="select-item-name">{{ item.title || item.id }}</span>
                  <code class="select-item-id code-font">{{ $t('(') }}ID: {{ item.id }}{{ $t(')') }}</code>
                </el-option>
              </el-select>
              <InfoBlock v-if="tryToExportEnvVariablePassword" type="warning" :title="$t('Exported passwords will be changed to an empty string by force')" />
            </el-form-item>

            <el-form-item :label="$t('Note')" prop="note">
              <el-input
                type="textarea"
                resize="none"
                :autosize="{minRows: 2}"
                maxlength="5000"
                v-model="form.note"></el-input>
              <InfoBlock :title="$t('Meaningful notes can provide a reliable reference for the future')" />
            </el-form-item>

            <el-form-item class="setup-footer">
              <el-button type="primary" v-prevent-re-click @click="submitData">{{ $t('Export') }}</el-button>
            </el-form-item>
          </el-form>
        </div>
      </el-main>

      <el-dialog
        :title="$t('Data exported')"
        :visible.sync="showDownloadFilename"
        width="750px">
        <div class="download-filename-dialog-content">
          <p class="text-good">{{ $t('Data exported') }}</p>
          <p>{{ $t('Exported content has been downloaded as a zip file:') }}</p>
          <p class="download-filename">
            <i class="fa fa-fw fa-3x fa-file-archive-o"></i>
            <code>{{ downloadFilename }}</code>
          </p>
        </div>
        <span slot="footer" class="dialog-footer">
          <el-button type="primary" @click="showDownloadFilename = false">
            {{ $t('Very good') }}
          </el-button>
        </span>
      </el-dialog>
    </el-container>
  </el-dialog>
</template>

<script>
import FileSaver from 'file-saver';

export default {
  name: 'ScriptSetExport',
  components: {
  },
  watch: {
    show(val) {
      if (!val) {
        this.$root.$emit('reload.scriptSetExportHistoryList');
      }
    },
  },
  methods: {
    async loadData() {
      let opt = {
        query: {
          fields: [
            'id',
            'title',
            'origin',
            'originId',
            'type',
            'autoTypeCasting',
            'lockedByUserId',
            'lockConfigMemberAllowMap',
          ]
        },
      };

      // Get related data
      // Script Set
      let apiRes = await this.T.callAPI_getAll('/api/v1/script-sets/do/list', opt);
      if (!apiRes || !apiRes.ok) return;

      let scriptSets = apiRes.data;

      // Compute lock status
      scriptSets.forEach(d => {
        d.isLocked = !this.can(d, [ 'scriptSet_readScriptCode', 'scriptSet_editScriptCode' ]);
      });

      // Skip hidden Script Sets
      scriptSets = scriptSets.filter(d => {
        return !this.common.shouldScriptSetHidden(d);
      });

      scriptSets.forEach(x => {
        this.common.appendSearchFields(x, ['id', 'title'])
      });

      this.scriptSets             = scriptSets;
      this.selectScriptSetOptions = scriptSets;

      // Connector
      apiRes = await this.T.callAPI_getAll('/api/v1/connectors/do/list', opt);
      if (!apiRes || !apiRes.ok) return;

      let connectors = apiRes.data;
      connectors.forEach(x => {
        this.common.appendSearchFields(x, ['id', 'title'])
      });

      this.connectors             = connectors;
      this.selectConnectorOptions = connectors;

      // Evn Variable
      apiRes = await this.T.callAPI_getAll('/api/v1/env-variables/do/list', opt);
      if (!apiRes || !apiRes.ok) return;

      let envVariables = apiRes.data;
      envVariables.forEach(x => {
        this.common.appendSearchFields(x, ['id', 'title'])
      });

      this.envVariables             = envVariables;
      this.selectEnvVariableOptions = envVariables;

      this.show = true;
    },
    async submitData() {
      try {
        await this.$refs.form.validate();
      } catch(err) {
        return console.error(err);
      }

      return await this.exportData();
    },
    async exportData() {
      let opt = {
        respType: 'blob',
        packResp: true,
        body    : this.T.jsonCopy(this.form),
      };

      let apiRes = await this.T.callAPI('post', '/api/v1/script-sets/do/export', opt);
      if (!apiRes || !apiRes.ok) return;

      let blob = new Blob([apiRes.data], {type: apiRes.extra.contentType});

      // Filename starts with a fixed prefix and follows date time
      let _prefix  = this.$store.getters.SYSTEM_INFO('_SCRIPT_EXPORT_FILE_PREFIX');
      let _timeTag = this.M().utcOffset('+08: 00').format('YYYYMMDD_HHmmss');
      let fileName = `${_prefix}${_timeTag}.zip`;
      FileSaver.saveAs(blob, fileName);

      this.downloadFilename     = fileName;
      this.showDownloadFilename = true;

      this.show = false;
    },

    doScriptSetFilter(q) {
      q = (q || '').toLowerCase().trim();
      if (!q) {
        this.selectScriptSetOptions = this.scriptSets;
      } else {
        this.selectScriptSetOptions = this.common.filterByKeywords(q, this.scriptSets);
      }
    },
    doConnectorFilter(q) {
      q = (q || '').toLowerCase().trim();
      if (!q) {
        this.selectConnectorOptions = this.connectors;
      } else {
        this.selectConnectorOptions = this.common.filterByKeywords(q, this.connectors);
      }
    },
    doEnvVariableFilter(q) {
      q = (q || '').toLowerCase().trim();
      if (!q) {
        this.selectEnvVariableOptions = this.envVariables;
      } else {
        this.selectEnvVariableOptions = this.common.filterByKeywords(q, this.envVariables);
      }
    },

    can(data, operation) {
      return this.common.lockConfigCan(data.lockedByUserId, data.lockConfigMemberAllowMap, operation);
    },
  },
  props: {
  },
  computed: {
    envVariableAutoTypeCastingMap() {
      return this.envVariables.reduce((acc, x) => {
        acc[x.id] = x.autoTypeCasting;
        return acc;
      }, {});
    },
    tryToExportEnvVariablePassword() {
      for (let i = 0; i < this.form.envVariableIds.length; i++) {
        let id = this.form.envVariableIds[i];
        if (this.envVariableAutoTypeCastingMap[id] === 'password') {
          return true;
        }
      }
      return false;
    },
  },
  data() {
    return {
      show: false,

      showDownloadFilename: false,
      downloadFilename    : null,

      scriptSets  : [],
      connectors  : [],
      envVariables: [],

      selectScriptSetOptions  : [],
      selectConnectorOptions  : [],
      selectEnvVariableOptions: [],

      form: {
        note            : '',
        scriptSetIds    : [],
        connectorIds    : [],
        envVariableIds  : [],
        includeSyncAPIs : false,
        includeAsyncAPIs: false,
        includeCronJobs : false,
      },
      formRules: {
        scriptSetIds: [
          {
            trigger : 'blur',
            message : this.$t('Please select at least one Script Set'),
            required: true,
            type    : 'array',
            min     : 1,
          },
        ],
        note: [
          {
            trigger : 'blur',
            message : this.$t('Please input note'),
            required: true,
            min     : 1,
          },
        ],
      },
    }
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.export-form {
  width: 620px;
}
.download-filename-dialog-content {
  text-align: center;
  display: block;
  font-size: 18px;
  line-height: 50px;
}
.download-filename {
  margin-top: 50px;
  font-size: 18px;
  letter-spacing: 1px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.download-filename > code {
  margin-top: 20px;
}

.el-checkbox.is-bordered {
  margin-right : 5px !important;
  margin-left: 0 !important;
}

.select-item-tag {
  width: 75px;
  text-align: center;
}
.select-item-name {
  padding-left: 10px;
}
.select-item-id {
  opacity: .7;
  font-size: 12px;
}
</style>
